/*
 * Copyright 2011 Raimon Rodriguez
 *
 * This file is part of sgfx.
 *
 * sgfx is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * sgfx is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with sgfx. If not, see <http://www.gnu.org/licenses/>.
 */

package com.googlecode.sgfx.controller;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.swing.EventListModel;
import com.google.common.base.Objects;
import com.google.common.primitives.Ints;
import com.googlecode.sgfx.base.ListModels;
import java.util.AbstractList;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import javax.swing.JList;
import javax.swing.event.ListSelectionListener;

/**
 *
 * @author raimon.rodriguez
 */
class SelectionEventList<E> extends AbstractList<E> {
    private JList listWidget;
    private EventList<E> listModel;


    SelectionEventList(JList pListWidget) {
        listWidget = pListWidget;
        listModel = ListModels.<E>newEventList(pListWidget.getModel());
        // TODO: this will cause firing events !!
        int[] selectedIndices = pListWidget.getSelectedIndices();
        listWidget.setModel(new EventListModel<E>(listModel));
        listWidget.setSelectedIndices(selectedIndices);
    }

    
    public void addListSelectionListener(ListSelectionListener pListener) {
        listWidget.addListSelectionListener(pListener);
    }

    public void removeListSelectionListener(ListSelectionListener pListener) {
        listWidget.removeListSelectionListener(pListener);
    }

    public void addListEventListener(ListEventListener<? super E> pListener) {
        listModel.addListEventListener(pListener);
    }

    public void removeListEventListener(ListEventListener<? super E> pListener) {
        listModel.removeListEventListener(pListener);
    }

    public boolean isSelectionEmpty() {
        return listWidget.isSelectionEmpty();
    }

    public int lastIndex() {
        if (listModel.isEmpty()) throw new IllegalStateException("list is empty");
        return listModel.size() - 1;
    }

    public int size() {
        return listModel.size();
    }

    public List<Integer> getSelectedIndices() {
        return Ints.asList(listWidget.getSelectedIndices());
    }

    public Collection<E> removeSelected() {
        List<Integer> selectedIndices = getSelectedIndices();
        int lowestSelectedIndex = selectedIndices.get(0);
        Deque<E> selectedItems = new ArrayDeque<E>(selectedIndices.size());
        Collections.sort(selectedIndices, Collections.reverseOrder());

        for (int index : selectedIndices) selectedItems.addFirst(listModel.remove(index));

        if (listModel.isEmpty()) {
            listWidget.clearSelection();
        } else {
            listWidget.setSelectedIndex(lowestSelectedIndex < listModel.size()?
                    lowestSelectedIndex : lastIndex());
        }
        
        return selectedItems;
    }

    @Override
    public boolean add(E pElement) {
        return listModel.add(pElement);
    }

    @Override
    public E remove(int index) {
        return listModel.remove(index);
    }
    
    public E get(int index) {
        return listModel.get(index);
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("items", listModel)
                .add("selection", getSelectedIndices()).toString();
    }
}